/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package se.sll.engagemangsindex.ejb;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.xml.ws.BindingProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import riv.itintegration.engagementindex._1.EngagementTransactionType;
import riv.itintegration.engagementindex._1.EngagementType;
import riv.itintegration.engagementindex.processnotification._1.rivtabp21.ProcessNotificationResponderInterface;
import riv.itintegration.engagementindex.processnotification._1.rivtabp21.ProcessNotificationResponderService;
import riv.itintegration.engagementindex.processnotificationresponder._1.ProcessNotificationType;
import riv.itintegration.registry._1.ServiceContractNamespaceType;
import riv.itintegration.registry.getlogicaladdresseesbyservicecontract._1.rivtabp21.GetLogicalAddresseesByServiceContractResponderInterface;
import riv.itintegration.registry.getlogicaladdresseesbyservicecontract._1.rivtabp21.GetLogicalAddresseesByServiceContractResponderService;
import riv.itintegration.registry.getlogicaladdresseesbyservicecontractresponder._1.GetLogicalAddresseesByServiceContractResponseType;
import riv.itintegration.registry.getlogicaladdresseesbyservicecontractresponder._1.GetLogicalAddresseesByServiceContractType;
import se.sll.engagemangsindex.dto.EngagementTypeImpl;


/**
 *
 * @author khaleddaham
 */
@Stateless
public class NotificationEjb {

    @Inject private LogicalAddressCache logicalAddressCache;
    @Inject private ConfigurationHolder configuration;
    private ProcessNotificationResponderInterface update = null;
    private GetLogicalAddresseesByServiceContractResponderInterface addresseesByContractPort = null;
    private BindingProvider bp = null;
    private BindingProvider logicalAddresseesBindingProvider = null;
    private static final Logger LOG = (Logger) LoggerFactory.getLogger(NotificationEjb.class);
    private String contract = "urn:riv:itintegration:engagementindex:ReceiveNotification:1";
    private static final String SERVICE_REGISTRY_ENDPOINT_URL = "";

    /**
     *
     */
    public NotificationEjb() {
        ProcessNotificationResponderService service = new ProcessNotificationResponderService(
                this.getClass().getResource("META-INF/ProcessNotificationInteraction_1.0_RIVTABP21.wsdl"));
        update = service.getProcessNotificationResponderPort();
        bp = (BindingProvider) update;

        GetLogicalAddresseesByServiceContractResponderService logicalAddresseesByServiceContract = new GetLogicalAddresseesByServiceContractResponderService(
                this.getClass().getResource("META-INF/GetLogicalAddresseesByServiceContractInteraction_1.0_RIVTABP21.wsdl"));
        addresseesByContractPort = logicalAddresseesByServiceContract.getGetLogicalAddresseesByServiceContractResponderPort();
        logicalAddresseesBindingProvider = (BindingProvider) addresseesByContractPort;
    }

    /**
     * 
     * @param service 
     */
    protected NotificationEjb(ProcessNotificationResponderService service) {
        update = service.getProcessNotificationResponderPort();
        bp = (BindingProvider) update;
    }

    /**
     * Takes an engagement and sends it as a notification to all addresses that we have in our
     * cache.
     * @param e
     */
    public void sendNotification(EngagementTypeImpl e, boolean deleteFlag) {
        LOG.debug("Sending notification for {}", e.toString());

        ProcessNotificationType updateType = new ProcessNotificationType();
        List<EngagementTransactionType> eTypeList = new ArrayList<EngagementTransactionType>();
        EngagementTransactionType eType = new EngagementTransactionType();
        eType.setDeleteFlag(deleteFlag);
        eType.setEngagement((EngagementType)e);
        eTypeList.add(eType);
        updateType.getEngagementTransaction().add(eType);

        /*
         * @TODO JMS and retry policy
         */
        try {
            for (String endpointURL : logicalAddressCache.getLogicalAddresses()) {
                bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
                update.processNotification(endpointURL, updateType);
            }
        } catch (Exception ex) {
            LOG.debug("Failed to send notificiation", ex);
        }
    }

    /**
     * 
     * @return 
     */
    protected List<String> getNotificationAddressList() {
        GetLogicalAddresseesByServiceContractType parameters = new GetLogicalAddresseesByServiceContractType();
        ServiceContractNamespaceType contractNamespaceType = new ServiceContractNamespaceType();
        contractNamespaceType.setServiceContractNamespace(this.contract);
        parameters.setServiceContractNameSpace(contractNamespaceType);
        logicalAddresseesBindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, SERVICE_REGISTRY_ENDPOINT_URL);
        GetLogicalAddresseesByServiceContractResponseType response = addresseesByContractPort.getLogicalAddresseesByServiceContract(configuration.getServiceCatalogue(), parameters);
        return response.getLogicalAddress();
    }

    /**
     * Used for mock tests.
     * @param responder 
     */
    protected void setProcessNotificationResponder(ProcessNotificationResponderInterface responder) {
        this.update = responder;
    }

    /**
     * Used for mock tests
     * @param addressCache 
     */
    protected void setLogicalAddressCache(LogicalAddressCache addressCache) {
        this.logicalAddressCache = addressCache;
    }

    /**
     * Used for mock tests
     * @param bp 
     */
    protected void setBindingProvider(BindingProvider bp) {
        this.bp = bp;
    }
}